﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Runtime.Serialization;
using System.Xml;

namespace Wardriver
{
    /// <summary>
    /// Data container for Wifi And GPS data. 
    /// This class holds wifi access points.
    /// </summary>
    public class WifiAP
    {
        private string _SSID;
        private byte[] _MAC;
        private string _MAC_String;

        private List<WifiEntry> _datapoints;

        /// <summary>
        /// SSID of AP.
        /// </summary>
        public string SSID { get { return _SSID; } }

        /// <summary>
        /// MAC of AP.
        /// </summary>
        public byte[] MAC { get { return _MAC; } }

        /// <summary>
        /// MAC String of AP.
        /// </summary>
        public string MAC_String { get { return _MAC_String; } }

        /// <summary>
        /// Appends a WifiEntry to the datapoints list.
        /// </summary>
        /// <param name="Data">The WifiEntry with Wifi and GPS Data.</param>
        public void AppendDataPoint(WifiEntry Data) 
        {
            if (Data.MAC_String != _MAC_String || Data.SSID != _SSID) 
            {
                // Not the same network. Ignore.
                return;
            }

            // Append
            _datapoints.Add(Data);
        }

        /// <summary>
        /// Gets the datapoints in the AP collection.
        /// </summary>
        public List<WifiEntry> GetDataPoints()
        {
            List<WifiEntry> temp = new List<WifiEntry>();

            foreach (WifiEntry item in _datapoints)
            {
                temp.Add(item);
            }

            // Return
            return temp;
        }

        /// <summary>
        /// Initiates the data class
        /// </summary>
        /// <param name="firstpoint">The first Entry to base the AP on</param>
        public WifiAP(WifiEntry firstpoint) 
        {
            // Prepare datastore
            _datapoints = new List<WifiEntry>();

            // Load data
            _SSID = firstpoint.SSID;
            _MAC = firstpoint.MAC;
            _MAC_String = firstpoint.MAC_String;

            // Append data
            AppendDataPoint(firstpoint);
        }
    }

    /// <summary>
    /// Suitable wardriving data output.
    /// </summary>
    public class WifiEntry
    {
        /// <summary>
        /// Background Data
        /// </summary>
        private NativeWifi.Wlan.WlanBssEntry _data;

        /// <summary>
        /// Internal GPS Point associated with this AP.
        /// </summary>
        private GPSEntry _gpspoint;

        /// <summary>
        /// Wifi SSID Name
        /// </summary>
        public string SSID
        {
            get
            {
                return Encoding.UTF8.GetString(_data.dot11Ssid.SSID);
            }
        }

        /// <summary>
        /// Wifi MAC Address as Bytes.
        /// </summary>
        public byte[] MAC
        {
            get
            {
                return _data.dot11Bssid;
            }
        }

        /// <summary>
        /// Wifi MAC Address as a String.
        /// </summary>
        public string MAC_String
        {
            get
            {
                byte[] macAddr = this.MAC;
                string tMac = "";
                for (int i = 0; i < macAddr.Length; i++)
                {
                    tMac += macAddr[i].ToString("x2").PadLeft(2, '0').ToUpper();
                }

                return tMac;
            }
        }

        /// <summary>
        /// Wifi Signal Strength. Range: 0.00 - 1.00 (%)
        /// </summary>
        public decimal SignalStrength 
        {
            get
            {
                return _data.linkQuality / 100;
            }
        }

        /// <summary>
        /// GPS Data
        /// </summary>
        public GPSEntry GPSData { get { return _gpspoint; } set { _gpspoint = value; } }

        /// <summary>
        /// Creates a Wifi Entry class.
        /// </summary>
        /// <param name="input">The base data to create from</param>
        public WifiEntry(NativeWifi.Wlan.WlanBssEntry input)
        {
            _data = input;
        }

        /// <summary>
        /// Creates a Wifi Entry class.
        /// </summary>
        /// <param name="input">The base data to create from</param>
        /// <param name="gpsData">The GPS Data to use</param>
        public WifiEntry(NativeWifi.Wlan.WlanBssEntry input, GPSEntry gpsData)
        {
            _data = input;
            _gpspoint = gpsData;
        }
    }
}
